package cn.example.vip.mall.api.filter;

import cn.example.vip.mall.api.hot.HotQueue;
import cn.example.vip.mall.api.permission.AuthVerifyInterceptor;
import cn.example.vip.mall.util.RespCode;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 将该过滤器放于
 * 1.{OrderedGatewayFilter@9765} "[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@50de907a}, order = 10000]"
 * 2.{OrderedGatewayFilter@9766} "[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@7645e64}, order = 10100]"
 * 这两个过滤器之间，
 * 1.RouteToRequestUrlFilter 实现权限验证
 * 2.LoadBalancerClientFilter 实现负载均衡
 * ApiFilter实现秒杀订单业务处理
 */
//@Configuration
public class ApiFilter implements GlobalFilter, Ordered {
	
	@Autowired
	private HotQueue hotQueue;
	@Autowired
	private AuthVerifyInterceptor authVerifyInterceptor;
	
	/**
	 * 全局拦截器
	 * 拦截秒杀抢购
	 * @param exchange
	 * @param chain
	 * @return
	 */
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
		// 跨域问题由网关配置解决
		
		// 放行登录和注册地址
		String uri = request.getPath().toString();
//		if(uri.equals("/user/info/login") || uri.equals("/user/info/register")){
//			return chain.filter(exchange);	// 放行
//		}
		// ---------------------------------------
		// 请求的权限拦截器,放行
		if(!authVerifyInterceptor.isInterceptor(exchange)){
			System.out.println("----isInterceptor.");
			return chain.filter(exchange);
		}
		// ---------------------------------------
		// 令牌校验
		Map<String, Object> jwtMap = authVerifyInterceptor.tokenInterceptor(exchange);
		if(jwtMap == null || !authVerifyInterceptor.rolePermission(exchange, jwtMap)){
			// 校验失败
			endProcess(exchange, RespCode.ACCESS_DENIED.getCode(), "Access denied");
		}
		// 校验成功,往请求头加上用户名
		String userName = jwtMap.get("username").toString();
		request.getHeaders().set("username", userName);
		
		// -------------------------------------
		// 热门秒杀商品的下单请求过滤
		if(uri.equals("/seckill/order")){
			seckillFilter(exchange, request, jwtMap.get("username").toString());
		}
		
		// NOT_HOT 由后端服务处理
		return chain.filter(exchange);
	}
	
	/**
	 * 执行优先级,Order值越小优先级越高
	 * 将该过滤器放于
	 * 1.{OrderedGatewayFilter@9765} "[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@50de907a}, order = 10000]"
	 * 2.{OrderedGatewayFilter@9766} "[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@7645e64}, order = 10100]"
	 * 这两个过滤器之间: [10000, 10100]
	 * @return
	 */
	@Override
	public int getOrder() {
		return 10001;
	}
	
	/**
	 * 热门商品过滤
	 * @param exchange
	 * @param request
	 * @param username
	 */
	public void seckillFilter(ServerWebExchange exchange, ServerHttpRequest request, String username) {
		// 获取信息
		String id = request.getQueryParams().getFirst("id");
		Integer num = Integer.valueOf(request.getQueryParams().getFirst("num"));
		// 排队结果
		Integer result = hotQueue.hotToQueue(username, id, num);
		
		// QUEUE_ING,HAS_QUEUE 调用热门抢购服务进行处理
		if(result == HotQueue.QUEUE_ING || result == HotQueue.QUEUE_ING){
			// 返回数据
			endProcess(exchange, result, "hot");
		}
	}
	
	/**
	 * 结束过滤器程序
	 * @param exchange
	 * @param type
	 */
	public void endProcess(ServerWebExchange exchange, Integer code, String type) {
		// 响应状态码
		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("code", code);
		resultMap.put("type", type);
		// 响应状态码200
		exchange.getResponse().setStatusCode(HttpStatus.OK);
		exchange.getResponse().setComplete();
		// 返回数据标头
		exchange.getResponse().getHeaders().add("msg", JSON.toJSONString(resultMap));
	}
}
